package com.awonsome.oss.resource;

import com.aliyun.oss.OSS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import java.util.Objects;

/**
 * oss:// 协议的 ProtocolResolver 实现。
 *
 * @author yangdejun
 * @date 2022/1/5 23:17
 */
public class OssStorageProtocolResolver
        implements ProtocolResolver, BeanFactoryPostProcessor, ResourceLoaderAware {

    // oss 协议
    public static final String PROTOCOL = "oss://";

    private static final Logger log = LoggerFactory.getLogger(OssStorageProtocolResolver.class);

    private ConfigurableListableBeanFactory beanFactory;

    private OSS oss;

    private OSS getOss() {
        if (Objects.isNull(this.oss)) {
            if (this.beanFactory.getBeansOfType(OSS.class).size() > 1) {
                log.warn("There are multiple OSS instances, consider marking one of them as @Primary to resolve oss protocol.");
            }
            this.oss = this.beanFactory.getBean(OSS.class);
        }
        return this.oss;
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        if (DefaultResourceLoader.class.isAssignableFrom(resourceLoader.getClass())) {
            ((DefaultResourceLoader) resourceLoader).addProtocolResolver(this);
        } else {
            log.warn("The provided delegate resource loader is not implementation" +
                    "of DefaultResourceLoader. Custom Protocol using oss:// prefix will not be enabled");
        }
    }

    @Override
    public Resource resolve(String location, ResourceLoader resourceLoader) {
        if (!location.startsWith(PROTOCOL)) {
            return null;
        }
        return new OssStorageResource(getOss(), location, beanFactory);
    }
}
